package com.itany.nmms.service.impl;

import com.itany.nmms.constant.DictConstant;
import com.itany.nmms.dao.ProductMapper;
import com.itany.nmms.dao.SequenceMapper;
import com.itany.nmms.entity.Product;
import com.itany.nmms.entity.ProductExample;
import com.itany.nmms.entity.Sequence;
import com.itany.nmms.entity.SequenceExample;
import com.itany.nmms.exception.FileUploadErrorException;
import com.itany.nmms.exception.ProductExistException;
import com.itany.nmms.exception.RequestParameterErrorException;
import com.itany.nmms.service.ProductService;
import com.itany.nmms.util.ParameterUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * Author:shixiaojun@itany.com
 * Date:2022/3/15 13:35
 * Version:1.0-SNAPSHOT
 */
@Service
@Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
public class ProductServiceImpl implements ProductService {

    @Autowired(required = false)
    private ProductMapper productMapper;

    @Autowired(required = false)
    private SequenceMapper sequenceMapper;

    @Override
    public void addProduct(String name, String price, MultipartFile file, String typeId) throws RequestParameterErrorException, ProductExistException, FileUploadErrorException {
        if(ParameterUtil.isNull(name) || ParameterUtil.isNull(price) || file.isEmpty() || ParameterUtil.isNull(typeId)){
            throw new RequestParameterErrorException("请求参数有误");
        }

        // 同一类型的商品名称不能重复
        ProductExample example = new ProductExample();
        example.or()
                .andNameEqualTo(name)
                .andProductTypeIdEqualTo(Integer.parseInt(typeId));
        List<Product> products = productMapper.selectByExample(example);
        if(!products.isEmpty()){
            throw new ProductExistException("该商品已经存在");
        }

        Product product = new Product();
        product.setName(name);
        product.setPrice(Double.parseDouble(price));
        product.setProductTypeId(Integer.parseInt(typeId));

        // 生成商品编号
        // 判断当前商品编号的序列号是否使用过
        // 根据商品编号的标志位去序列号表中进行查询
        SequenceExample sequenceExample = new SequenceExample();
        sequenceExample.or()
                .andNameEqualTo(DictConstant.PRODUCT_NO_PREFIX);
        List<Sequence> sequences = sequenceMapper.selectByExample(sequenceExample);
        // 如果没有查询到对应的数据,表示尚未生成过
        if(sequences.isEmpty()){
            // 因此,设置一个初始值
            Sequence sequence = new Sequence();
            sequence.setName(DictConstant.PRODUCT_NO_PREFIX);
            sequence.setValue(DictConstant.PRODUCT_NO_SEQUENCE_INIT_VALUE);
            // 执行添加操作
            sequenceMapper.insertSelective(sequence);

            // 生成此时的商品编号
            product.setProductNo(DictConstant.PRODUCT_NO_PREFIX+new SimpleDateFormat("yyyyMMdd").format(new Date())+sequence.getValue());
        } else{
            // 如果查询到对应的数据,则此时的数据应该有且仅有一条
            // 取出这一条数据
            Sequence sequence = sequences.get(0);
            // 判断当前序列号的值是否达到了最大值
            if(DictConstant.PRODUCT_NO_SEQUENCE_MAX_VALUE.equals(sequence.getValue())){
                // 如果达到了最大值,则下一个值为初始值
                sequence.setValue(DictConstant.PRODUCT_NO_SEQUENCE_INIT_VALUE);
            } else{
                // 如果尚未达到最大值,则下一个在原有值的基础+1
                sequence.setValue(String.format("%06d",Integer.parseInt(sequence.getValue())+1));
            }

            // 执行修改操作
            sequenceMapper.updateByPrimaryKeySelective(sequence);

            // 生成此时的商品编号
            product.setProductNo(DictConstant.PRODUCT_NO_PREFIX+new SimpleDateFormat("yyyyMMdd").format(new Date())+sequence.getValue());
        }


        // 上传商品图片
        // 在服务器根目录下创建一个专门用于存放所有商品图片的根目录
        // 并且在该根目录下根据上传日期,每天创建一个以当前年月日命名的子目录
        // 当前的所有图片上传到对应的子目录中
        String path = DictConstant.PRODUCT_IMAGE_ROOT_DIRECTORY+new SimpleDateFormat("yyyyMMdd").format(new Date());

        // 创建对应的目录
//        String cp = session.getServletContext().getRealPath(path);

        try {
            String cp = ResourceUtils.getURL("classpath:").getPath()+path;
            System.out.println("***********cp:"+cp);
            File f = new File(cp);
            f.mkdirs();

            // 为了防止图片名称重复,可以为每一个图片添加一个毫秒数的后缀
            String fileName = file.getOriginalFilename();
            fileName = fileName.substring(0,fileName.lastIndexOf("."))+"-"+new Date().getTime()+fileName.substring(fileName.lastIndexOf("."));

            // 生成上传的文件信息,将其交给商品对象
            product.setImage(path+"/"+fileName);

            // 添加商品
            productMapper.insertSelective(product);
            // 上传商品图片
            file.transferTo(new File(cp,fileName));
        } catch (IOException e) {
            throw new FileUploadErrorException("商品图片上传失败");
        }


    }

    @Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
    @Override
    public List<Product> findAll() {
        List<Product> products = productMapper.selectAll();
        return products;
    }

    @Transactional(propagation = Propagation.SUPPORTS,readOnly = true)
    @Override
    public Product findById(String id) throws RequestParameterErrorException {
        if(ParameterUtil.isNull(id)){
            throw new RequestParameterErrorException("请求参数有误");
        }
        Product product = productMapper.selectByPrimaryKey(Integer.parseInt(id));
        return product;
    }

    @Override
    public void modifyProduct(String id, String name, String price, MultipartFile file, String typeId) throws RequestParameterErrorException, ProductExistException, FileUploadErrorException {
        if(ParameterUtil.isNull(id) || ParameterUtil.isNull(name) || ParameterUtil.isNull(price) || ParameterUtil.isNull(typeId)){
            throw new RequestParameterErrorException("请求参数有误");
        }

        // 同一个类型下的商品名称不能重复
        // 数据库中存在且不是当前的则抛出异常
        ProductExample example = new ProductExample();
        example.or()
                .andNameEqualTo(name)
                .andProductTypeIdEqualTo(Integer.parseInt(typeId))
                .andProductIdNotEqualTo(Integer.parseInt(id));
        List<Product> products = productMapper.selectByExample(example);
        if(!products.isEmpty()){
            throw new ProductExistException("该商品已经存在");
        }

        Product product = new Product();
        product.setProductId(Integer.parseInt(id));
        product.setName(name);
        product.setPrice(Double.parseDouble(price));
        product.setProductTypeId(Integer.parseInt(typeId));

        // 判断是否上传了图片
        if(!file.isEmpty()){
            // 如果上传了图片,则进行图片的业务
            String path = DictConstant.PRODUCT_IMAGE_ROOT_DIRECTORY+new SimpleDateFormat("yyyyMMdd").format(new Date());

            try {
                // 创建对应的目录
//              String cp = session.getServletContext().getRealPath(path);
                String cp = ResourceUtils.getURL("classpath:").getPath()+path;
                System.out.println("***********cp:"+cp);
                File f = new File(cp);
                f.mkdirs();

                // 为了防止图片名称重复,可以为每一个图片添加一个毫秒数的后缀
                String fileName = file.getOriginalFilename();
                fileName = fileName.substring(0,fileName.lastIndexOf("."))+"-"+new Date().getTime()+fileName.substring(fileName.lastIndexOf("."));

                // 生成上传的文件信息,将其交给商品对象
                product.setImage(path+"/"+fileName);

                productMapper.updateByPrimaryKeySelective(product);
                file.transferTo(new File(cp,fileName));
            } catch (IOException e) {
                throw new FileUploadErrorException("商品图片上传出错");
            }
        } else{
            // 如果没有上传图片,则直接修改
            productMapper.updateByPrimaryKeySelective(product);
        }

    }

    @Override
    public void removeProduct(String id) throws RequestParameterErrorException {
        if(ParameterUtil.isNull(id)){
            throw new RequestParameterErrorException("请求参数有误");
        }
        productMapper.deleteByPrimaryKey(Integer.parseInt(id));
    }
}
